package com.hksj.base.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hksj.base.mapper.RoomPropertyMapper;
import com.hksj.base.query.InstantaneousPropertyQuery;
import com.hksj.base.query.InstantaneousValueQuery;
import com.hksj.base.query.RoomPropertyQuery;
import com.hksj.base.vo.*;
import com.hksj.common.core.util.EasyExcelUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class RoomPropertyService {
    @Autowired
    private RoomPropertyMapper roomPropertyMapper;
    @Autowired
    private DefaultDeviceService defaultDeviceService;

    private Integer range = 12;

    public Page<CompositeRoomPropertyVO> pageRoom(RoomPropertyQuery query) {
        //查房间信息
        Page<CompositeRoomPropertyVO> page = new Page<>(query.getPageNum(), query.getPageSize());
        page.setRecords(new ArrayList<>());
        List<RoomVO> roomList = roomPropertyMapper.listRoom(query);

        if(!ObjectUtils.isEmpty(roomList)){
            //获取要查询的天数
            List<DateTime> days = DateUtil.rangeToList(DateUtil.parseDate(query.getStartTime()), DateUtil.parseDate(query.getEndTime()), DateField.DAY_OF_MONTH);
            //分页处理
            List<DayRoomVO> allDayRoomVOList = new ArrayList<>();
            List<DayRoomVO> queryRoomList = new ArrayList<>();
            if (!ObjectUtils.isEmpty(days)){
                for (DateTime day : days) {
                    for (RoomVO roomVO : roomList) {
                        DayRoomVO dayRoomVO = new DayRoomVO();
                        dayRoomVO.setDay(DateUtil.formatDate(day));
                        dayRoomVO.setRoomId(roomVO.getId());
                        dayRoomVO.setName(roomVO.getName());
                        dayRoomVO.setPaths(roomVO.getPaths());
                        dayRoomVO.setDepartmentId(roomVO.getDepartmentId());
                        dayRoomVO.setDepartmentName(roomVO.getDepartmentName());
                        allDayRoomVOList.add(dayRoomVO);
                    }
                }
            }
            page.setTotal(allDayRoomVOList.size());
            if (query.getDisAblePage()){
                queryRoomList = allDayRoomVOList;
            }else{
                Integer startIndex = query.getStartRow();
                Integer endIndex = query.getStartRow() + query.getPageSize();
                if (startIndex <= allDayRoomVOList.size()){
                    if (endIndex <= allDayRoomVOList.size()){
                        queryRoomList = allDayRoomVOList.subList(startIndex,endIndex);
                    }else{
                        queryRoomList = allDayRoomVOList.subList(startIndex, allDayRoomVOList.size());
                    }
                }
            }

            //查询结果
            if (!ObjectUtils.isEmpty(queryRoomList)){
                List<Long> queryRoomIdList = queryRoomList.stream().map(q -> q.getRoomId()).collect(Collectors.toList());
                Set<String> queryDays = queryRoomList.stream().map(q -> q.getDay()).collect(Collectors.toSet());
                List<DayPropertyVO> dayPropertyList = new ArrayList<>();

                //查压差
                List<DeviceVO> pressureDeviceList = roomPropertyMapper.listPressureDevice(queryRoomIdList,"YC");
                //存在设备
                wrapDayProperty(pressureDeviceList,Arrays.asList("pressure"),queryDays,query,dayPropertyList);

                //查温湿
                List<DeviceVO> temperatureHumidityDeviceList = roomPropertyMapper.listTemperatureHumidityDevice(queryRoomIdList);
                wrapDayProperty(temperatureHumidityDeviceList,Arrays.asList("SongFwd","Huifsd"),queryDays,query,dayPropertyList);

                //每间房间的设备
                List<DeviceVO> allDeviceList = new ArrayList<>();
                allDeviceList.addAll(pressureDeviceList);
                allDeviceList.addAll(temperatureHumidityDeviceList);
                Map<Long, List<DeviceVO>> roomDeviceMap = new ConcurrentHashMap<>();
                Map<String, DeviceVO> deviceMap = new ConcurrentHashMap<>();
                if (!ObjectUtils.isEmpty(allDeviceList)){
                    roomDeviceMap = allDeviceList.stream().collect(Collectors.groupingByConcurrent(DeviceVO::getRoomId));
                    deviceMap = allDeviceList.stream().collect(Collectors.groupingBy(DeviceVO::getId,
                            Collectors.collectingAndThen(
                                Collectors.toList(),
                                tList -> tList.get(0)
                            )
                    ));
                }

                //按天按deviceId抽象出map
                Map<String, Map<String, Map<String, DayPropertyVO>>> dayDevicePropertyMap = new HashMap<>();
                if (!ObjectUtils.isEmpty(dayPropertyList)){
                    dayDevicePropertyMap = dayPropertyList.stream().collect(Collectors.groupingBy(DayPropertyVO::getDay, Collectors.groupingBy(DayPropertyVO::getDeviceId, Collectors.toMap(DayPropertyVO::getProperty,Function.identity()))));
                }

                //房间信息map
                Map<Long, RoomVO> roomInfoMap = roomList.stream().collect(Collectors.toMap(RoomVO::getId, Function.identity()));

                //结果封装
                List<CompositeRoomPropertyVO> res = new ArrayList<>();
                for (DayRoomVO dayRoomVO : queryRoomList) {
                    CompositeRoomPropertyVO compositeRoomPropertyVO = new CompositeRoomPropertyVO();
                    compositeRoomPropertyVO.setId(dayRoomVO.getRoomId());
                    compositeRoomPropertyVO.setDay(dayRoomVO.getDay());
                    compositeRoomPropertyVO.setPaths(roomInfoMap.get(dayRoomVO.getRoomId()).getPaths());
                    compositeRoomPropertyVO.setDepartmentId(roomInfoMap.get(dayRoomVO.getRoomId()).getDepartmentId());
                    compositeRoomPropertyVO.setDepartmentName(roomInfoMap.get(dayRoomVO.getRoomId()).getDepartmentName());

                    List<DeviceVO> roomDeviceList = roomDeviceMap.getOrDefault(dayRoomVO.getRoomId(),new ArrayList<>());
                    for (DeviceVO deviceVO : roomDeviceList) {
                        DayPropertyVO pressure = dayDevicePropertyMap.getOrDefault(dayRoomVO.getDay(), new HashMap<>())
                                .getOrDefault(deviceVO.getId(), new HashMap<>())
                                .get("pressure");

                        DayPropertyVO songFwd = dayDevicePropertyMap.getOrDefault(dayRoomVO.getDay(), new HashMap<>())
                                .getOrDefault(deviceVO.getId(), new HashMap<>())
                                .get("SongFwd");

                        DayPropertyVO huifsd = dayDevicePropertyMap.getOrDefault(dayRoomVO.getDay(), new HashMap<>())
                                .getOrDefault(deviceVO.getId(), new HashMap<>())
                                .get("Huifsd");

                        if (!ObjectUtils.isEmpty(pressure)){
                            compositeRoomPropertyVO.setPressure(pressure.getValue());
                            compositeRoomPropertyVO.setPressureTime(pressure.getCreateTime());
                            compositeRoomPropertyVO.setDeviceNameYC(deviceMap.get(pressure.getDeviceId()).getName());
                        }

                        if (!ObjectUtils.isEmpty(songFwd)){
                            compositeRoomPropertyVO.setTemperature(songFwd.getValue());
                        }

                        if (!ObjectUtils.isEmpty(huifsd)){
                            compositeRoomPropertyVO.setHumidity(huifsd.getValue());
                            compositeRoomPropertyVO.setTemperatureHumidityTime(huifsd.getCreateTime());
                            compositeRoomPropertyVO.setDeviceNameKTJZ(deviceMap.get(huifsd.getDeviceId()).getName());
                        }
                    }
                    res.add(compositeRoomPropertyVO);
                }
                defaultDeviceService.wrapAddr(res);
                page.setRecords(res);
            }
        }
        return page;
    }

    private void wrapDayProperty(List<DeviceVO> deviceList,List<String> propertyList,Set<String> days,RoomPropertyQuery query,List<DayPropertyVO> dayPropertyList){
        if (!ObjectUtils.isEmpty(deviceList)){
            Map<String, List<DeviceVO>> pressureProductDeviceMap = deviceList.stream().collect(Collectors.groupingBy(DeviceVO::getProductId));
            //分天查询
            for (String day : days) {
                DateTime timePoint = DateUtil.parseDateTime(day + " " + query.getTimePoint());
                Long rangeStartTime = DateUtil.offsetHour(timePoint,- range).getTime();
                Long rangeEndTime = DateUtil.offsetHour(timePoint,range).getTime();
                for (String productId : pressureProductDeviceMap.keySet()) {
                    //查询目标数据索引集合
                    InstantaneousValueQuery instantaneousValueQuery = new InstantaneousValueQuery();
                    instantaneousValueQuery.setProductId(productId);
                    Set<String> deviceIdList = pressureProductDeviceMap.get(productId).stream().map(item -> item.getId()).collect(Collectors.toSet());
                    instantaneousValueQuery.setDeviceIdList(deviceIdList);
                    instantaneousValueQuery.setStartTime(rangeStartTime);
                    instantaneousValueQuery.setEndTime(rangeEndTime);
                    instantaneousValueQuery.setTimePoint(timePoint.getTime());
                    instantaneousValueQuery.setPropertyList(propertyList);
                    instantaneousValueQuery.setTableName(defaultDeviceService.getTableName(productId));
                    List<InstantaneousValueVO> instantaneousValueParams = roomPropertyMapper.listInstantaneousValueParams(instantaneousValueQuery);

                    //根据目标数据索引集合查具体数据
                    for (InstantaneousValueVO instantaneousValueParam : instantaneousValueParams) {
                        InstantaneousPropertyQuery instantaneousPropertyQuery = new InstantaneousPropertyQuery();
                        instantaneousPropertyQuery.setDeviceId(instantaneousValueParam.getDeviceId());
                        instantaneousPropertyQuery.setProperty(instantaneousValueParam.getProperty());
                        instantaneousPropertyQuery.setStartTime(rangeStartTime);
                        instantaneousPropertyQuery.setEndTime(rangeEndTime);
                        instantaneousPropertyQuery.setTimePoint(timePoint.getTime());
                        instantaneousPropertyQuery.setTableName(defaultDeviceService.getTableName(productId));
                        instantaneousPropertyQuery.setDiff(instantaneousValueParam.getDiff());
                        DayPropertyVO propertyVO = roomPropertyMapper.getInstantaneousProperty(instantaneousPropertyQuery);
                        if (!ObjectUtils.isEmpty(propertyVO)){
                            propertyVO.setDay(day);
                            dayPropertyList.add(propertyVO);
                        }
                    }
                }
            }
        }
    }

    public void exportRoomProperty(RoomPropertyQuery query, HttpServletResponse response) {
        query.setDisAblePage(true);
        List<CompositeRoomPropertyVO> records = pageRoom(query).getRecords();
        List<RoomPropertyExportVO> res = new ArrayList<>();
        if (!ObjectUtils.isEmpty(records)){
            for (CompositeRoomPropertyVO record : records) {
                RoomPropertyExportVO roomPropertyExportVO = new RoomPropertyExportVO();
                roomPropertyExportVO.setDay(record.getDay());
                roomPropertyExportVO.setBuildingName(record.getBuildingName());
                roomPropertyExportVO.setFloorName(record.getFloorName());
                roomPropertyExportVO.setDepartmentName(record.getDepartmentName());
                roomPropertyExportVO.setRoomName(record.getRoomName());
                roomPropertyExportVO.setDeviceNameKTJZ(record.getDeviceNameKTJZ());
                roomPropertyExportVO.setTemperature(record.getTemperature());
                roomPropertyExportVO.setHumidity(record.getHumidity());
                roomPropertyExportVO.setTemperatureHumidityTime(DateUtil.formatDateTime(record.getTemperatureHumidityTime()));
                roomPropertyExportVO.setDeviceNameYC(record.getDeviceNameYC());
                roomPropertyExportVO.setPressure(record.getPressure());
                roomPropertyExportVO.setPressureTime(DateUtil.formatDateTime(record.getPressureTime()));
                res.add(roomPropertyExportVO);
            }
        }

        String fileName = new StringBuffer()
                .append("房间指标")
                .append(new SimpleDateFormat("_yyyyMMddHHmmss").format(new Date()))
                .toString();
        EasyExcelUtil.exportExcelData(response,fileName,res,RoomPropertyExportVO.class);
    }
}
